%{
	
#include <stdio.h>
#include "y.tab.h"


%}

%union  {
	int entero;
	double doble;
	char cadena;
	float flotante;
	struct token * tptr;

}

%token <entero>INT INT1 INT2 INT3 INT4 INT5 INT6 INT7 INT8 ENTERO
%token <doble>REAL
%token <cadena> CHAR CADENA
%token <flotante> FLOAT
%token <tptr> IDENTIFICADOR

%token MEI MAY MAI MEN DIF O_LOG Y_LOG O_BIT Y_BIT 
%token O_ASIGBIT Y_ASIGBIT SUMA_ASIG MULTIPLICA_ASIG INCREMENTO DECREMENTO
%token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR CONTINUE BREAK RETURN EXIT /*IDENTIFICADOR /*ENTERO /*CADENA */
%token /*CHAR INT1 INT2 INT3 INT4 INT5 INT6 INT7 INT8*/ CONST VOID MAIN MALLOC DELETE COMENTARIO
%token TYPEDEF EXTERN STATIC AUTO REGISTER

%token TYPE_NAME LONG SHORT STRUCT MOD_ASSIGN DIV_ASSIGN IGUAL UNSIGNED RIGHT_OP SIZEOF GOTO RIGHT_ASSIGN ENUM 
%token XOR_ASSIGN VOLATILE SIGNED PTR_OP LEFT_ASSIGN DOUBLE SUB_ASSIGN LEFT_OP UNION /*FLOAT*/ ELLIPSIS

%type <entero> assignment_expression
%type <double> external_declaration

%error-verbose

%right '?' ':'
%left ','
%left O_LOG
%left Y_LOG
%left O_BIT

%left Y_BIT
%left IGUAL DIF
%left MEN MAY MEI MAI

%left '+' '-'
%left '*' '/' '%'

%start translation_unit   
//%start statement_list

%%
//gramatica

primary_expression
	: IDENTIFICADOR
	| ENTERO

	| CADENA
	| '(' expression ')'
	;

postfix_expression
	: primary_expression
	| postfix_expression '[' expression ']'
	| postfix_expression '(' ')'
	| postfix_expression '(' argument_expression_list ')'
	| postfix_expression '.' IDENTIFICADOR
	| postfix_expression PTR_OP IDENTIFICADOR
	| postfix_expression INCREMENTO
	| postfix_expression DECREMENTO
	;

argument_expression_list
	: assignment_expression  								{printf ("assignment expression\n"); }
	| argument_expression_list ',' assignment_expression
	;

unary_expression
	: postfix_expression
	| INCREMENTO unary_expression
	| DECREMENTO unary_expression
	| unary_operator cast_expression
	| SIZEOF unary_expression
	| SIZEOF '(' type_name ')'
	;

unary_operator
	: Y_BIT
	| '*'
	| '+'
	| '-'
	| '~'
	| '!' 
	;

cast_expression
	: unary_expression
	| '(' type_name ')' cast_expression
	;

multiplicative_expression
	: cast_expression
	| multiplicative_expression '*' cast_expression
	| multiplicative_expression '/' cast_expression
	| multiplicative_expression '%' cast_expression
	;

additive_expression
	: multiplicative_expression
	| additive_expression '+' multiplicative_expression    { printf("addwf f,d \n"); }
	| additive_expression '-' multiplicative_expression
	;

shift_expression
	: additive_expression
	| shift_expression LEFT_OP additive_expression
	| shift_expression RIGHT_OP additive_expression
	;

relational_expression
	: shift_expression
	| relational_expression MEN shift_expression
	| relational_expression MAY shift_expression
	| relational_expression MEI shift_expression
	| relational_expression MAI shift_expression
	;

equality_expression
	: relational_expression
	| equality_expression IGUAL relational_expression
	| equality_expression DIF relational_expression
	;

and_expression									
	: equality_expression						//{printf(" andlw k \n ");}
	| and_expression Y_BIT equality_expression  
	;

exclusive_or_expression
	: and_expression							//{printf(" xorlw k \n xorwf f,d \n ");}
	| exclusive_or_expression '^' and_expression 
	;

inclusive_or_expression
	: exclusive_or_expression					//{printf(" xorlw k \n ");}
	| inclusive_or_expression O_BIT exclusive_or_expression
	;

logical_and_expression
	: inclusive_or_expression
	| logical_and_expression Y_LOG inclusive_or_expression
	;

logical_or_expression
	: logical_and_expression
	| logical_or_expression O_LOG logical_and_expression
	;

conditional_expression
	: logical_or_expression
	| logical_or_expression '?' expression ':' conditional_expression
	;

assignment_expression
	: conditional_expression
	| unary_expression assignment_operator assignment_expression 
	;

assignment_operator
	: '='
	| MULTIPLICA_ASIG
	| DIV_ASSIGN
	| MOD_ASSIGN
	| SUMA_ASIG
	| SUB_ASSIGN
	| LEFT_ASSIGN
	| RIGHT_ASSIGN
	| Y_ASIGBIT
	| XOR_ASSIGN
	| O_ASIGBIT
	;

expression
	: assignment_expression 		{ printf("\n movlw k ..."
										" movf f,d  \n");} 
	| expression ',' assignment_expression
	;

constant_expression
	: conditional_expression
	;

declaration
	: declaration_specifiers ';'  
	| declaration_specifiers init_declarator_list ';'
	;

declaration_specifiers
	: storage_class_specifier
	| storage_class_specifier declaration_specifiers
	| type_specifier
	| type_specifier declaration_specifiers
	| type_qualifier
	| type_qualifier declaration_specifiers
	;

init_declarator_list
	: init_declarator
	| init_declarator_list ',' init_declarator
	;

init_declarator
	: declarator
	| declarator '=' initializer {printf ("declaration \n"); }
	;

storage_class_specifier
	: TYPEDEF
	| EXTERN
	| STATIC
	| AUTO
	| REGISTER
	;

type_specifier
	: VOID
	| CHAR
	| SHORT
	| INT
	| INT1
	| INT2
	| INT3
	| INT4
	| INT5
	| INT6
	| INT7
	| INT8
	| LONG
	| FLOAT
	| DOUBLE
	| SIGNED
	| UNSIGNED
	| struct_or_union_specifier
	| enum_specifier
	| TYPE_NAME
	;

struct_or_union_specifier
	: struct_or_union IDENTIFICADOR '{' struct_declaration_list '}'
	| struct_or_union '{' struct_declaration_list '}'
	| struct_or_union IDENTIFICADOR
	;

struct_or_union
	: STRUCT
	| UNION
	;

struct_declaration_list
	: struct_declaration
	| struct_declaration_list struct_declaration
	;

struct_declaration
	: specifier_qualifier_list struct_declarator_list ';'
	;

specifier_qualifier_list
	: type_specifier specifier_qualifier_list
	| type_specifier
	| type_qualifier specifier_qualifier_list
	| type_qualifier
	;

struct_declarator_list
	: struct_declarator
	| struct_declarator_list ',' struct_declarator
	;

struct_declarator
	: declarator
	| ':' constant_expression
	| declarator ':' constant_expression
	;

enum_specifier
	: ENUM '{' enumerator_list '}'
	| ENUM IDENTIFICADOR '{' enumerator_list '}'
	| ENUM IDENTIFICADOR
	;

enumerator_list
	: enumerator
	| enumerator_list ',' enumerator
	;

enumerator
	: IDENTIFICADOR
	| IDENTIFICADOR '=' constant_expression
	;

type_qualifier
	: CONST
	| VOLATILE
	;

declarator
	: pointer direct_declarator
	| direct_declarator
	;

direct_declarator
	: IDENTIFICADOR
	| '(' declarator ')'
	| direct_declarator '[' constant_expression ']'
	| direct_declarator '[' ']'
	| direct_declarator '(' parameter_type_list ')'
	| direct_declarator '(' identifier_list ')'
	| direct_declarator '(' ')'
	;

pointer
	: '*'
	| '*' type_qualifier_list
	| '*' pointer
	| '*' type_qualifier_list pointer
	;

type_qualifier_list
	: type_qualifier
	| type_qualifier_list type_qualifier
	;


parameter_type_list
	: parameter_list
	| parameter_list ',' ELLIPSIS
	;

parameter_list
	: parameter_declaration
	| parameter_list ',' parameter_declaration
	;

parameter_declaration
	: declaration_specifiers declarator
	| declaration_specifiers abstract_declarator
	| declaration_specifiers
	;

identifier_list
	: IDENTIFICADOR
	| identifier_list ',' IDENTIFICADOR
	;

type_name
	: specifier_qualifier_list
	| specifier_qualifier_list abstract_declarator
	;

abstract_declarator
	: pointer
	| direct_abstract_declarator
	| pointer direct_abstract_declarator
	;

direct_abstract_declarator
	: '(' abstract_declarator ')'
	| '[' ']'
	| '[' constant_expression ']'
	| direct_abstract_declarator '[' ']'
	| direct_abstract_declarator '[' constant_expression ']'
	| '(' ')'
	| '(' parameter_type_list ')'
	| direct_abstract_declarator '(' ')'
	| direct_abstract_declarator '(' parameter_type_list ')'
	;

initializer
	: assignment_expression
	| '{' initializer_list '}'
	| '{' initializer_list ',' '}'
	;

initializer_list
	: initializer
	| initializer_list ',' initializer
	;

statement
	: labeled_statement
	| compound_statement
	| expression_statement
	| selection_statement     
	| iteration_statement    { printf(" iter  \n"); }
	| jump_statement
	;

labeled_statement
	: IDENTIFICADOR ':' statement
	| CASE constant_expression ':' statement
	| DEFAULT ':' statement
	;

compound_statement
	: '{' '}'
	| '{' statement_list '}'  
	| '{' declaration_list '}'
	| '{' declaration_list statement_list '}'
	;

declaration_list
	: declaration
	| declaration_list declaration
	;

statement_list                
	: statement					
	| statement_list statement
	;

expression_statement
	: ';'
	| expression ';'
	;

selection_statement
	: IF '(' expression ')' statement				{printf ("IF SINK=1 \n            BCF PORTA,0\n ELSE\n BSF PORTA,0 \nENDIF"); }	
	| IF '(' expression ')' statement ELSE statement
	| SWITCH '(' expression ')' statement
	;

iteration_statement
	: WHILE '(' expression ')' statement			{ printf("Etiqueta \n ......\n	......\nbtfss PORTA,4\n goto Etiqueta \n");}
	| DO statement WHILE '(' expression ')' ';'     { printf("Etiqueta \n ......\n	......\nbtfss PORTA,4\n goto Etiqueta \n");}
	| FOR '(' expression_statement expression_statement ')' statement
	| FOR '(' expression_statement expression_statement expression ')' statement { printf("	movlw	NumeroVeces\n 	movwf	Contador\nLazo \n	decfsz\n Contador,F\n goto Lazo \n");}
	;

jump_statement
	: GOTO IDENTIFICADOR ';'
	| CONTINUE ';'
	| BREAK ';'
	| RETURN ';'
	| RETURN expression ';'
	;

translation_unit					
	: external_declaration	
	| translation_unit external_declaration
	;

external_declaration
	: function_definition
	| declaration { //printf("ext declaration %f \n", $<doble>1);
	            printf("\n__CONFIG _CP_OFF & _WDT_OFF & _PWRTE_ON & _XT_OSC \n LIST P=16F84A \n	INCLUDE <P16F84A.INC> \nORG 0 " );
				printf("Inicio \n bsf STATUS,RP0 ;Acceso al Banco 1 \n clrf TRISB     ;configuramos puerto B como Salida \n ..."
						"	movlw b'00001111' \n movwf TRISA     ;configuro los 5 bit del puerto A como entrada \n ..."
						" bcf STATUS,RP0  ;Acceso al Banco 0 \n clrf PORTA      ; Borro el Puerto A \n ..."
				   		" clrf PORTB	; Borro el Puerto B \n" ); }
	;

function_definition
	: declaration_specifiers declarator declaration_list compound_statement
	| declaration_specifiers declarator compound_statement
	| declarator declaration_list compound_statement
	| declarator compound_statement
	;
			

// fin de la gramatica	
%%

yyerror (char const *msg) /* Llamada por yyparse ante un error */
{
   //char *s;
   fprintf (stderr, "yyerror: %s\n", msg);  /* Esta implementación por defecto nos valdrá */
                        /* Si no creamos esta función, habrá que enlazar con –ly en el
                        momento de compilar para usar una implementación por defecto */
}

/*if(argc == 2) {
   if(!(yyout = fopen(argv[2], "w"))) {
      printf("ERROR: El archivo de salida no pudo ser leído.\n");
      exit(0);
   }
}*/

//void main (int argc, char **argv) {
//	   
////	if(argc > 1) {
////	      if(!(yyin = fopen(argv[1], "r"))) {
////	         printf("ERROR: El archivo de entrada no pudo ser leído.\n");
////	         exit(0);
////	      }
////	   }
//  //Acciones a ejecutar antes del análisis
//  if (yyparse()) {
//      printf ("yyparse: 1 \n");
//     
//     }
//  //Acciones a ejecutar después del análisis
//}




